home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / machines / i386 / machine.c next >
C/C++ Source or Header  |  1999-01-01  |  47KB  |  1,254 lines

  1. /*  Code generator for Intel 80386 or higher.                   */
  2.  
  3. #include "supp.h"
  4.  
  5. static char FILE_[]=__FILE__;
  6.  
  7. /*  Public data that MUST be there.                             */
  8.  
  9. /* Name and copyright. */
  10. char cg_copyright[]="vbcc code-generator for i386 V0.5 (c) in 1996-99 by Volker Barthelmann";
  11.  
  12. /*  Commandline-flags the code-generator accepts                */
  13. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,
  14.                     0,0,0,0};
  15. char *g_flags_name[MAXGF]={"cpu","fpu","no-delayed-popping","const-in-data",
  16.                            "merge-constants","elf","longalign","safe-fp"};
  17. union ppi g_flags_val[MAXGF];
  18.  
  19. /*  Alignment-requirements for all types in bytes.              */
  20. zlong align[16];
  21.  
  22. /*  Alignment that is sufficient for every object.              */
  23. zlong maxalign;
  24.  
  25. /*  CHAR_BIT of the target machine.                             */
  26. zlong char_bit;
  27.  
  28. /*  Sizes of all elementary types in bytes.                     */
  29. zlong sizetab[16];
  30.  
  31. /*  Minimum and Maximum values each type can have.              */
  32. /*  Must be initialized in init_cg().                           */
  33. zlong t_min[32];
  34. zulong t_max[32];
  35.  
  36. /*  Names of all registers.                                     */
  37. char *regnames[MAXR+1]={"noreg","%eax","%ecx","%edx","%ebx",
  38.                                 "%esi","%edi","%ebp","%esp",
  39.                                 "%st(0)","%st(1)","%st(2)","%st(3)",
  40.                                 "%st(4)","%st(5)","%st(6)","%st(7)"};
  41.  
  42. /*  The Size of each register in bytes.                         */
  43. zlong regsize[MAXR+1];
  44.  
  45. /*  Type which can store each register. */
  46. struct Typ *regtype[MAXR+1];
  47.  
  48. /*  regsa[reg]!=0 if a certain register is allocated and should */
  49. /*  not be used by the compiler pass.                           */
  50. int regsa[MAXR+1];
  51.  
  52. /*  Specifies which registers may be scratched by functions.    */
  53. int regscratch[MAXR+1]={0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1};
  54.  
  55.  
  56. /****************************************/
  57. /*  Some private data and functions.    */
  58. /****************************************/
  59.  
  60. static long malign[16]=  {1,1,2,2,2,2,2,1,2,1,1,1,2,1};
  61. static long msizetab[16]={0,1,2,4,4,4,8,0,4,0,0,0,4,0};
  62.  
  63. struct Typ ltyp={LONG},ldbl={DOUBLE};
  64.  
  65. #define DATA 0
  66. #define BSS 1
  67. #define CODE 2
  68.  
  69. static int section=-1,newobj;
  70. static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="";
  71. static int is_const(struct Typ *);
  72. static const int ax=1,cx=2,dx=3,bx=4,si=5,di=6,bp=7,sp=8;
  73. static char x_t[]={'?','b','w','l','l','s','l','v','l','a','s','u','e','f','?','?'};
  74. static int is_const(struct Typ *);
  75. static void pr(FILE *,struct IC *);
  76. static void function_top(FILE *,struct Var *,long);
  77. static void function_bottom(FILE *f,struct Var *,long);
  78.  
  79. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  80.  
  81. static long loff,stackoffset,notpopped,dontpop;
  82.  
  83. static char *ccs[]={"z","nz","l","ge","le","g","mp"};
  84. static char *ccu[]={"z","nz","b","ae","be","a","mp"};
  85. static char *logicals[]={"or","xor","and"};
  86. static char *arithmetics[]={"sal","sar","add","sub","imul","div","mod"};
  87. static char *farithmetics[]={"f?","f?","fadd","fsub","fmul","fdiv","fsubr","fdivr"};
  88. static char *dct[]={"","byte","short","long","long","long","long","long","long"};
  89. static pushedsize,pushorder=2;
  90. static int fst[8];
  91. static int cxl,dil,sil;
  92. static char *idprefix="",*labprefix="";
  93.  
  94. static struct fpconstlist {
  95.     struct fpconstlist *next;
  96.     int label,typ;
  97.     union atyps val;
  98. } *firstfpc;
  99.  
  100. static int addfpconst(struct obj *o,int t)
  101. {
  102.     struct fpconstlist *p=firstfpc;
  103.     t&=NQ;
  104.     if(g_flags[4]&USEDFLAG){
  105.         for(p=firstfpc;p;p=p->next){
  106.             if(t==p->typ){
  107.                 eval_const(&p->val,t);
  108.                 if(t==FLOAT&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return(p->label);
  109.                 if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) return(p->label);
  110.             }
  111.         }
  112.     }
  113.     p=mymalloc(sizeof(struct fpconstlist));
  114.     p->next=firstfpc;
  115.     p->label=++label;
  116.     p->typ=t;
  117.     p->val=o->val;
  118.     firstfpc=p;
  119.     return(p->label);
  120. }
  121. static void probj2(FILE *f,struct obj *p,int t)
  122. /*  Gibt Objekt auf Bildschirm aus                      */
  123. {
  124.   if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,"(");
  125.   if(p->flags&VARADR) fprintf(f,"$");
  126.   if((p->flags&VAR)&&!(p->flags®)) {
  127.     if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  128.       if(p->v->offset<0) fprintf(f,"%ld(%%esp)",(long)(loff-zl2l(p->v->offset)+zl2l(p->val.vlong))-stackoffset+pushedsize);
  129.       else           fprintf(f,"%ld(%%esp)",(long)(zl2l(p->v->offset)+zl2l(p->val.vlong)-stackoffset));
  130.     }else{
  131.       if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  132.       if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&NQ)!=FUNKT){
  133.         fprintf(f,"%sl%ld",labprefix,zl2l(p->v->offset));
  134.       }else{
  135.         fprintf(f,"%s%s",idprefix,p->v->identifier);
  136.       }
  137.     }
  138.   }
  139.   if(p->flags®){
  140.     if(p->reg>8){
  141.       int i;
  142.       for(i=0;i<8;i++){
  143.         if(fst[i]==p->reg)
  144.           fprintf(f,"%s",regnames[i+9]);
  145.       }
  146.     }else{
  147.       t&=NQ;
  148.       if(t==CHAR&&!(p->flags&DREFOBJ)) fprintf(f,"%%%cl",regnames[p->reg][2]);
  149.       else if(t==SHORT&&!(p->flags&DREFOBJ)) fprintf(f,"%%%s",regnames[p->reg]+2);
  150.       else fprintf(f,"%s",regnames[p->reg]);
  151.     }
  152.   }
  153.   if(p->flags&KONST){
  154.     if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  155.       fprintf(f,"%sl%d",labprefix,addfpconst(p,t));
  156.     }else{
  157.       fprintf(f,"$");printval(f,&p->val,t&NU,0);
  158.     }
  159.   }
  160.   if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,")");
  161. }
  162. static void fxch(FILE *f,int i)
  163. {
  164.     int m;
  165.     fprintf(f,"\tfxch\t%s\n",regnames[i+9]);
  166.     m=fst[0];fst[0]=fst[i];fst[i]=m;
  167. }
  168. static int freest(void)
  169. {
  170.     int i;
  171.     for(i=0;i<8;i++){
  172.         if(fst[i]<0) return(i);
  173.     }
  174.     for(i=0;i<8;i++){
  175.         if(fst[i]==0) return(i);
  176.     }
  177.     ierror(0);
  178. }
  179. static void fpush(FILE *f)
  180. {
  181.     int i;
  182.     if(fst[7]>0){
  183.         i=freest();
  184.         if(fst[i]==0) fprintf(f,"\tffree\t%s\n",regnames[i+9]);
  185.         fxch(f,i);fxch(f,7);
  186.     }
  187.     for(i=7;i>0;i--)
  188.         fst[i]=fst[i-1];
  189.     fst[0]=-1;
  190. }
  191. static void fpop(void)
  192. {
  193.     int i;
  194. /*    if(fst[0]>0&®s[fst[0]]) ierror(0);*/
  195.     for(i=0;i<7;i++)
  196.         fst[i]=fst[i+1];
  197.     fst[7]=-1;
  198. }
  199. static void fload(FILE *f,struct obj *o,int t)
  200. {
  201.     fprintf(f,"\tfld");
  202.     if((o->flags&(REG|DREFOBJ))==REG) fprintf(f,"\t");
  203.         else fprintf(f,"%c\t",x_t[t&NQ]);
  204.     probj2(f,o,t);fprintf(f,"\n");
  205.     fpush(f);
  206. }
  207. static void fstore(FILE *f,struct obj *o,int t)
  208. {
  209.     int i;
  210.     if((o->flags&(REG|DREFOBJ))==REG){
  211.         for(i=0;i<8;i++)
  212.             if(fst[i]==o->reg) fst[i]=0;
  213.         fst[0]=o->reg;
  214.     }else{
  215.         fprintf(f,"\tfstp%c\t",x_t[t&NQ]);probj2(f,o,t);
  216.         fpop();fprintf(f,"\n");
  217.     }
  218. }
  219. static void prfst(FILE *f,char *s)
  220. {
  221.     int i;
  222.     if(DEBUG==0) return;
  223.     fprintf(f,"*\t%s\t",s);
  224.     for(i=0;i<8;i++){
  225.         if(fst[i]>=0){
  226.             if(fst[i]==0) fprintf(f,"+++ ");
  227.               else        fprintf(f,"%s ",regnames[fst[i]]+3);
  228.         }else{
  229.             fprintf(f,"--- ");
  230.         }
  231.     }
  232.     fprintf(f,"\n");
  233. }
  234. static void finit(void)
  235. {
  236.     int i;
  237.     for(i=0;i<8;i++){
  238.         if(regs[i+9])
  239.             fst[i]=i+9;
  240.         else
  241.             fst[i]=-1;
  242.     }
  243. }
  244. static void forder(FILE *f)
  245. {
  246.     int i,m,unordered;
  247.     prfst(f,"forder");
  248.     for(i=0;i<8;i++){
  249.         if(fst[i]==0){fprintf(f,"\tffree\t%s\n",regnames[i+9]);fst[i]=-1;}
  250.     }
  251. oloop:
  252.     unordered=0;
  253.     for(i=0;i<8;i++){
  254.         if(fst[i]>0&&fst[i]!=i+9&®s[fst[i]]){unordered=1;break;}
  255.     }
  256.     if(!unordered) return;
  257.     if(fst[0]>=0&®s[fst[0]]){
  258.         if(fst[0]!=9){
  259.             fxch(f,fst[0]-9);
  260.             goto oloop;
  261.         }else{
  262.             fxch(f,freest());
  263.         }
  264.     }
  265.     for(i=1;i<8;i++){
  266.         if(fst[i]>=0&&fst[i]!=i+9&®s[fst[i]]&&fst[i]!=9){
  267.             fxch(f,i);
  268.             goto oloop;
  269.         }
  270.     }
  271.     if(regs[9]){
  272.         for(i=1;i<8;i++){
  273.             if(fst[i]==9){ fxch(f,i);return;}
  274.         }
  275.     }
  276. }
  277. static void pr(FILE *f,struct IC *p)
  278. {
  279.     int i;
  280.     for(;pushorder>2;pushorder>>=1){
  281.         for(i=1;i<=8;i++){
  282.             if(regs[i]&pushorder){
  283.                 fprintf(f,"\tpopl\t%s\n",regnames[i]);
  284.                 stackoffset+=4;regs[i]&=~pushorder;
  285.             }
  286.         }
  287.     }
  288.     for(i=1;i<=8;i++)
  289.         if(regs[i]&2) regs[i]&=~2;
  290. }
  291. static void function_top(FILE *f,struct Var *v,long offset)
  292. /*  erzeugt Funktionskopf                       */
  293. {
  294.     int i;
  295.     if(section!=CODE){fprintf(f,codename);section=CODE;}
  296.     if(v->storage_class==EXTERN) fprintf(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
  297.     fprintf(f,"%s%s:\n",idprefix,v->identifier);
  298.     for(pushedsize=0,i=1;i<sp;i++){
  299.         if(regused[i]&&!regscratch[i]){
  300.             fprintf(f,"\tpushl\t%s\n",regnames[i]);
  301.             pushedsize+=4;
  302.         }
  303.     }
  304.     if(offset) fprintf(f,"\tsubl\t$%ld,%%esp\n",offset);
  305. }
  306. static void function_bottom(FILE *f,struct Var *v,long offset)
  307. /*  erzeugt Funktionsende                       */
  308. {
  309.     int i;
  310.     forder(f);
  311.     if(offset) fprintf(f,"\taddl\t$%ld,%%esp\n",offset);
  312.     for(i=sp-1;i>0;i--){
  313.         if(regused[i]&&!regscratch[i]){
  314.             fprintf(f,"\tpopl\t%s\n",regnames[i]);
  315.         }
  316.     }
  317.     fprintf(f,"\tret\n");
  318. }
  319. static int is_const(struct Typ *t)
  320. /*  Tests if a type can be placed in the code-section.  */
  321. {
  322.     if(!(t->flags&(CONST|STRINGCONST))){
  323.         do{
  324.             if(t->flags&(CONST|STRINGCONST)) return(1);
  325.             if((t->flags&NQ)!=ARRAY) return(0);
  326.             t=t->next;
  327.         }while(1);
  328.     }else return(1);
  329. }
  330. static int compare_objects(struct obj *o1,struct obj *o2)
  331. {
  332.     if(o1->flags==o2->flags&&o1->am==o2->am){
  333.         if(!(o1->flags&VAR)||(o1->v==o2->v&&zleqto(o1->val.vlong,o2->val.vlong))){
  334.             if(!(o1->flags®)||o1->reg==o2->reg){
  335.                 return(1);
  336.             }
  337.         }
  338.     }
  339.     return(0);
  340. }
  341. static int get_reg(FILE *f,struct IC *p,int type)
  342. {
  343.     int i;
  344.     /*  If we can use a register which was already used by the compiler */
  345.     /*  or it is a sratch register then we can use it without problems. */
  346.     for(i=1;i<=8;i++){
  347.         if(!regs[i]&&(regused[i]||regscratch[i])&®ok(i,type,0)){
  348.             regs[i]=2;
  349.             return(i);
  350.         }
  351.     }
  352.     /*  Otherwise we have to save this register.                        */
  353.     /*  We may not use a register which is used in this IC.             */
  354.     for(i=1;i<=8;i++){
  355.         if(regs[i]<2&®ok(i,type,0)
  356.             &&(!(p->q1.flags®)||p->q1.reg!=i)
  357.             &&(!(p->q2.flags®)||p->q2.reg!=i)
  358.             &&(!(p->z.flags®)||p->z.reg!=i) ){
  359.  
  360.             fprintf(f,"\tpushl\t%s\n",regnames[i]);
  361.             /*  Mark register as pushed (taking care of the order). */
  362.             pushorder<<=1; regs[i]|=pushorder;
  363.             stackoffset-=4;
  364.             return(i);
  365.         }
  366.     }
  367.     ierror(0);
  368. }
  369. static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
  370. /*  Generates code to move object q (or register qr) into object z (or  */
  371. /*  register zr).                                                       */
  372. {
  373.   t&=NQ;
  374.   if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
  375.   if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
  376.   if(qr&&zr){
  377.     if(qr!=zr)
  378.       fprintf(f,"\tmovl\t%s,%s\n",regnames[qr],regnames[zr]);
  379.     return;
  380.   }
  381.   if(zr&&(q->flags&KONST)){
  382.     eval_const(&q->val,t);
  383.     if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
  384.       fprintf(f,"\txorl\t%s,%s\n",regnames[zr],regnames[zr]);
  385.       return;
  386.     }
  387.   }
  388.   fprintf(f,"\tmov%c\t",x_t[t&NQ]);
  389.   if(qr){
  390.     if(t==SHORT) fprintf(f,"%%%s",regnames[qr]+2);
  391.     else if(t==CHAR) fprintf(f,"%%%cl",regnames[qr][2]);
  392.     else fprintf(f,"%s",regnames[qr]);
  393.   }else
  394.     probj2(f,q,t);
  395.   fprintf(f,",");
  396.   if(zr){
  397.     if(t==SHORT) fprintf(f,"%%%s",regnames[zr]+2);
  398.     else if(t==CHAR) fprintf(f,"%%%cl",regnames[zr][2]);
  399.     else fprintf(f,"%s",regnames[zr]);
  400.   }else
  401.     probj2(f,z,t);
  402.   fprintf(f,"\n");
  403. }
  404. static long pof2(zulong x)
  405. /*  Yields log2(x)+1 oder 0. */
  406. {
  407.     zulong p;int ln=1;
  408.     p=ul2zul(1L);
  409.     while(ln<=32&&zulleq(p,x)){
  410.         if(zuleqto(x,p)) return(ln);
  411.         ln++;p=zuladd(p,p);
  412.     }
  413.     return(0);
  414. }
  415.  
  416. /****************************************/
  417. /*  End of private fata and functions.  */
  418. /****************************************/
  419.  
  420.  
  421. int init_cg(void)
  422. /*  Does necessary initializations for the code-generator. Gets called  */
  423. /*  once at the beginning and should return 0 in case of problems.      */
  424. {
  425.     int i;
  426.     /*  Initialize some values which cannot be statically initialized   */
  427.     /*  because they are stored in the target's arithmetic.             */
  428.     maxalign=l2zl(4L);
  429.     char_bit=l2zl(8L);
  430.     if(g_flags[6]&USEDFLAG){
  431.         for(i=SHORT;i<16;i++) malign[i]=4;
  432.     }
  433.     for(i=0;i<16;i++){
  434.         sizetab[i]=l2zl(msizetab[i]);
  435.         align[i]=l2zl(malign[i]);
  436.     }
  437.     for(i=1;i<= 8;i++) {regsize[i]=l2zl(4L);regtype[i]=<yp;}
  438.     for(i=9;i<=16;i++) {regsize[i]=l2zl(8L);regtype[i]=&ldbl;}
  439.  
  440.     /*  Initialize the min/max-settings. Note that the types of the     */
  441.     /*  host system may be different from the target system and you may */
  442.     /*  only use the smallest maximum values ANSI guarantees if you     */
  443.     /*  want to be portable.                                            */
  444.     /*  That's the reason for the subtraction in t_min[INT]. Long could */
  445.     /*  be unable to represent -2147483648 on the host system.          */
  446.     t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  447.     t_min[CHAR]=l2zl(-128L);
  448.     t_min[SHORT]=l2zl(-32768L);
  449.     t_min[LONG]=zlsub(l2zl(-2147483647L),l2zl(1L));
  450.     t_min[INT]=t_min[LONG];
  451.     t_max[CHAR]=ul2zul(127L);
  452.     t_max[SHORT]=ul2zul(32767UL);
  453.     t_max[LONG]=ul2zul(2147483647UL);
  454.     t_max[INT]=t_max[LONG];
  455.     t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  456.     t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  457.     t_max[UNSIGNED|LONG]=ul2zul(4294967295UL);
  458.     t_max[UNSIGNED|INT]=t_max[UNSIGNED|LONG];
  459.     /*  Reserve a few registers for use by the code-generator.      */
  460.     /*  We only reserve the stack-pointer here.                     */
  461.     regsa[sp]=1;
  462.     /*  We need at least one free slot in the flaoting point stack  */
  463.     regsa[16]=1;regscratch[16]=0;
  464.     /*  Use l%d as labels and _%s as identifiers by default. If     */
  465.     /*  -elf is specified we use .l%d and %s instead.               */
  466.     if(g_flags[5]&USEDFLAG) labprefix="."; else idprefix="_";
  467.     return(1);
  468. }
  469.  
  470. int freturn(struct Typ *t)
  471. /*  Returns the register in which variables of type t are returned. */
  472. /*  If the value cannot be returned in a register returns 0.        */
  473. {
  474.     if((t->flags&NQ)==FLOAT||(t->flags&NQ)==DOUBLE) return 9;
  475.     if((t->flags&NQ)<=POINTER) return 1;
  476.     return 0;
  477. }
  478.  
  479. int regok(int r,int t,int mode)
  480. /*  Returns 0 if register r cannot store variables of   */
  481. /*  type t. If t==POINTER and mode!=0 then it returns   */
  482. /*  non-zero only if the register can store a pointer   */
  483. /*  and dereference a pointer to mode.                  */
  484. {
  485.     if(r==0) return(0);
  486.     t&=NQ;
  487.     if(r>8){
  488.       if(g_flags[7]&USEDFLAG) return 0;
  489.       if(t==FLOAT||t==DOUBLE) return 1;
  490.         else                  return 0;
  491.     }
  492.     if(t==CHAR&&(r==si||r==di||r==bp)) return 0;
  493.     if(t<=LONG) return 1;
  494.     if(t==POINTER) return 1;
  495.     return 0;
  496. }
  497.  
  498. int dangerous_IC(struct IC *p)
  499. /*  Returns zero if the IC p can be safely executed     */
  500. /*  without danger of exceptions or similar things.     */
  501. /*  vbcc may generate code in which non-dangerous ICs   */
  502. /*  are sometimes executed although control-flow may    */
  503. /*  never reach them (mainly when moving computations   */
  504. /*  out of loops).                                      */
  505. /*  Typical ICs that generate exceptions on some        */
  506. /*  machines are:                                       */
  507. /*      - accesses via pointers                         */
  508. /*      - division/modulo                               */
  509. /*      - overflow on signed integer/floats             */
  510. {
  511.     int c=p->code;
  512.     if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  513.         return(0);
  514.     if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
  515.         return(1);
  516.     return(0);
  517. }
  518.  
  519. int must_convert(np p,int t)
  520. /*  Returns zero if code for converting np to type t    */
  521. /*  can be omitted.                                     */
  522. /*  In this generic 32bit RISC cpu pointers and 32bit   */
  523. /*  integers have the same representation and can use   */
  524. /*  the same registers.                                 */
  525. {
  526.     int o=p->ntyp->flags,op=o&NQ,tp=t&NQ;
  527.     if(tp==POINTER&&op==POINTER) return(0);
  528.     if((t&UNSIGNED)&&(o&UNSIGNED)&&zleqto(sizetab[tp],sizetab[op])) return(0);
  529.     if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return(0);
  530.  
  531.     return(1);
  532. }
  533.  
  534. void gen_ds(FILE *f,zlong size,struct Typ *t)
  535. /*  This function has to create <size> bytes of storage */
  536. /*  initialized with zero.                              */
  537. {
  538.     if(newobj) fprintf(f,"%ld\n",zl2l(size));
  539.         else   fprintf(f,"\t.space\t%ld\n",zl2l(size));
  540.     newobj=0;
  541. }
  542.  
  543. void gen_align(FILE *f,zlong align)
  544. /*  This function has to make sure the next data is     */
  545. /*  aligned to multiples of <align> bytes.              */
  546. {
  547.     if(!zlleq(align,l2zl(1L))) fprintf(f,"\t.align\t4\n");
  548. }
  549.  
  550. void gen_var_head(FILE *f,struct Var *v)
  551. /*  This function has to create the head of a variable  */
  552. /*  definition, i.e. the label and information for      */
  553. /*  linkage etc.                                        */
  554. {
  555.     int constflag;
  556.     if(v->clist) constflag=is_const(v->vtyp);
  557.     if(v->storage_class==STATIC){
  558.         if((v->vtyp->flags&NQ)==FUNKT) return;
  559.         if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  560.         if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  561.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  562.         if(section!=BSS) fprintf(f,"\t.align\t4\n%sl%ld:\n",labprefix,zl2l(v->offset));
  563.             else fprintf(f,"\t.lcomm\t%sl%ld,",labprefix,zl2l(v->offset));
  564.         newobj=1;
  565.     }
  566.     if(v->storage_class==EXTERN){
  567.         fprintf(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
  568.         if(v->flags&(DEFINED|TENTATIVE)){
  569.             if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  570.             if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  571.             if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  572.             if(section!=BSS) fprintf(f,"\t.align\t4\n%s%s:\n",idprefix,v->identifier);
  573.                 else fprintf(f,"\t.comm\t%s%s,",idprefix,v->identifier);
  574.             newobj=1;
  575.         }
  576.     }
  577. }
  578.  
  579. void gen_dc(FILE *f,int t,struct const_list *p)
  580. /*  This function has to create static storage          */
  581. /*  initialized with const-list p.                      */
  582. {
  583.     fprintf(f,"\t.%s\t",dct[t&NQ]);
  584.     if(!p->tree){
  585.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  586.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  587.             unsigned char *ip;
  588.             ip=(unsigned char *)&p->val.vdouble;
  589.             fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  590.             if((t&NQ)==DOUBLE){
  591.                 fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  592.             }
  593.         }else{
  594.             printval(f,&p->val,t&NU,0);
  595.         }
  596.     }else{
  597.         int m=p->tree->o.flags;
  598.         p->tree->o.flags&=~VARADR;
  599.         probj2(f,&p->tree->o,t&NU);
  600.         p->tree->o.flags=m;
  601.     }
  602.     fprintf(f,"\n");newobj=0;
  603. }
  604.  
  605. /*  The main code-generation routine.                   */
  606. /*  f is the stream the code should be written to.      */
  607. /*  p is a pointer to a doubly linked list of ICs       */
  608. /*  containing the function body to generate code for.  */
  609. /*  v is a pointer to the function.                     */
  610. /*  offset is the size of the stackframe the function   */
  611. /*  needs for local variables.                          */
  612. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  613. {
  614.     int c,t,lastcomp=0,reg;
  615.     if(DEBUG&1) printf("gen_code()\n");
  616.     for(c=1;c<=15;c++) regs[c]=regsa[c];
  617.     regs[16]=0;
  618.     loff=((zl2l(offset)+1)/2)*2;
  619.     function_top(f,v,loff);
  620.     stackoffset=notpopped=dontpop=0;
  621.     finit();
  622.     for(;p;pr(f,p),p=p->next){
  623.         c=p->code;t=p->typf;
  624.         if(c==NOP) continue;
  625.         if(c==SUBPFP) c=SUB;
  626.         if(c==SUBIFP) c=SUB;
  627.         if(c==ADDI2P) c=ADD;
  628.         if(c==ALLOCREG){
  629.             regs[p->q1.reg]=1;
  630.             continue;
  631.         }
  632.         if(c==FREEREG){
  633.             if(p->q1.reg>=9){
  634.                 for(c=0;c<8;c++)
  635.                     if(fst[c]==p->q1.reg) fst[c]=0;
  636.             }
  637.             regs[p->q1.reg]=0;
  638.             continue;
  639.         }
  640.         if(notpopped&&!dontpop){
  641.             int flag=0;
  642.             if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
  643.                 fprintf(f,"\taddl\t$%ld,%%esp\n",notpopped);
  644.                 stackoffset+=notpopped;notpopped=0;
  645.             }
  646.         }
  647.         if(c==LABEL) {forder(f);fprintf(f,"%sl%d:\n",labprefix,t);continue;}
  648.         if(c>=BEQ&&c<=BRA){
  649.             forder(f);
  650.             if(lastcomp&UNSIGNED) fprintf(f,"\tj%s\t%sl%d\n",ccu[c-BEQ],labprefix,t);
  651.                 else              fprintf(f,"\tj%s\t%sl%d\n",ccs[c-BEQ],labprefix,t);
  652.             continue;
  653.         }
  654.         if(c==MOVETOREG){
  655.             if(p->z.reg>8){
  656.                 for(c=0;c<8;c++){
  657.                     if(fst[c]==p->z.reg) fst[c]=0;
  658.                 }
  659.                 fload(f,&p->q1,DOUBLE);
  660.                 fst[0]=p->z.reg;
  661.                 continue;
  662.             }
  663.             move(f,&p->q1,0,0,p->z.reg,LONG);
  664.             continue;
  665.         }
  666.         if(c==MOVEFROMREG){
  667.             if(p->q1.reg>8){
  668.                 if(fst[0]!=p->q1.reg){
  669.                     for(c=0,reg=-1;c<8;c++){
  670.                         if(fst[c]==p->q1.reg) reg=c;
  671.                     }
  672.                     if(reg<0) ierror(0);
  673.                     fxch(f,reg);
  674.                 }
  675.                 fprintf(f,"\tfstpl\t");probj2(f,&p->z,DOUBLE);
  676.                 fprintf(f,"\n");fpop();
  677.                 continue;
  678.             }
  679.             move(f,0,p->q1.reg,&p->z,0,LONG);
  680.             continue;
  681.         }
  682.         if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ){
  683.             reg=get_reg(f,p,LONG);
  684.             move(f,&p->q1,0,0,reg,LONG);
  685.             p->q1.flags|=REG;p->q1.reg=reg;
  686.             p->q1.flags&=~KONST;
  687.         }
  688.         if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ){
  689.             reg=get_reg(f,p,LONG);
  690.             move(f,&p->q2,0,0,reg,LONG);
  691.             p->q2.flags|=REG;p->q2.reg=reg;
  692.             p->q2.flags&=~KONST;
  693.         }
  694.         if((p->z.flags&(DREFOBJ|REG))==DREFOBJ){
  695.             reg=get_reg(f,p,LONG);
  696.             move(f,&p->z,0,0,reg,LONG);
  697.             p->z.flags|=REG;p->z.reg=reg;
  698.             p->z.flags&=~KONST;
  699.         }
  700.         if(c>=CONVCHAR&&c<=CONVULONG){
  701.             int to;
  702.             if(c==CONVCHAR) to=CHAR;
  703.             if(c==CONVUCHAR) to=(UNSIGNED|CHAR);
  704.             if(c==CONVSHORT) to=SHORT;
  705.             if(c==CONVUSHORT) to=(UNSIGNED|SHORT);
  706.             if(c==CONVINT) to=INT;
  707.             if(c==CONVUINT) to=(UNSIGNED|INT);
  708.             if(c==CONVLONG) to=INT;
  709.             if(c==CONVULONG) to=(UNSIGNED|INT);
  710.             if(c==CONVFLOAT) to=FLOAT;
  711.             if(c==CONVDOUBLE) to=DOUBLE;
  712.             if(c==CONVPOINTER) to=(UNSIGNED|INT);
  713.             if((t&NU)==LONG) t=INT;
  714.             if((t&NU)==(UNSIGNED|LONG)||(t&NU)==POINTER) t=(UNSIGNED|INT);
  715.             if((to&NQ)<=INT&&(t&NQ)<=INT){
  716.                 if(isreg(z)) reg=p->z.reg;
  717.                 else if(isreg(q1)&®ok(p->q1.reg,t,0)) reg=p->q1.reg;
  718.                 else reg=get_reg(f,p,((to&NQ)==CHAR||(t&NQ)==CHAR)?CHAR:LONG);
  719.                 if((to&NQ)<=SHORT){
  720.                     fprintf(f,"\tmov%c%cl\t",(to&UNSIGNED)?'z':'s',x_t[to&NQ]);
  721.                     probj2(f,&p->q1,to);
  722.                     fprintf(f,",%s\n",regnames[reg]);
  723.                 }else{
  724.                     move(f,&p->q1,0,0,reg,to);
  725.                 }
  726.                 move(f,0,reg,&p->z,0,t);
  727.                 continue;
  728.             }
  729.             if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  730.                 if((to&NQ)==FLOAT||(to&NQ)==DOUBLE){
  731.                     if(isreg(q1)&&fst[0]==p->q1.reg){
  732.                         if(isreg(z)){
  733.                             if(p->z.reg==fst[0]) continue;
  734.                             for(reg=0,c=7;c>=0;c--){
  735.                                 if(fst[c]==p->z.reg){reg=c;break;}
  736.                                 if(fst[c]<0) reg=c;
  737.                             }
  738.                             fst[reg]=p->z.reg;
  739.                         }
  740.                         fprintf(f,"\tfst%c\t",x_t[t&NQ]);
  741.                         probj2(f,&p->z,t);fprintf(f,"\n");
  742.                         continue;
  743.                     }
  744.                     fload(f,&p->q1,to);
  745.                     fstore(f,&p->z,t);
  746.                     continue;
  747.                 }
  748.                 if((to&NQ)<=SHORT){
  749.                     if(isreg(q1)){
  750.                         reg=p->q1.reg;
  751.                         if(to&UNSIGNED){
  752.                             fprintf(f,"\tandl\t$%ld,%s\n",(to&NQ)==CHAR?255L:65535L,regnames[reg]);
  753.                         }else{
  754. /*                            fprintf(f,"\tc%ctl\t%s\n",x_t[to&NQ],regnames[reg]);*/
  755.                             if((to&NQ)==SHORT){
  756.                                 fprintf(f,"\tmovswl\t%%%s,%s\n",regnames[reg]+2,regnames[reg]);
  757.                             }else{
  758.                                 fprintf(f,"\tmovsbl\t%%%cl,%s\n",regnames[reg][2],regnames[reg]);
  759.                             }
  760.                         }
  761.                     }else{
  762.                         reg=get_reg(f,p,LONG);
  763.                         if(to&UNSIGNED){
  764.                             fprintf(f,"\tmovz%cl\t",x_t[to&NQ]);
  765.                         }else{
  766.                             fprintf(f,"\tmovs%cl\t",x_t[to&NQ]);
  767.                         }
  768.                         probj2(f,&p->q1,to);fprintf(f,",%s\n",regnames[reg]);
  769.                     }
  770.                     fprintf(f,"\tpushl\t%s\n",regnames[reg]);
  771.                     fprintf(f,"\tfildl\t(%s)\n\taddl\t$4,%s\n",regnames[sp],regnames[sp]);
  772.                 }else{
  773.                     if(to&UNSIGNED){
  774.                         fprintf(f,"\tpushl\t$0\n\tpushl\t");stackoffset-=4;
  775.                         probj2(f,&p->q1,to);
  776.                         fprintf(f,"\n\tfildq\t(%s)\n\taddl\t$8,%s\n",regnames[sp],regnames[sp]);
  777.                         stackoffset+=4;
  778.                     }else{
  779.                         if(isreg(q1)){
  780.                             fprintf(f,"\tpushl\t%s\n\tfildl\t(%s)\n\taddl\t$4,%s\n",regnames[p->q1.reg],regnames[sp],regnames[sp]);
  781.                         }else{
  782.                             fprintf(f,"\tfildl\t");probj2(f,&p->q1,t);
  783.                             fprintf(f,"\n");
  784.                         }
  785.                     }
  786.                 }
  787.                 fpush(f);
  788.                 fstore(f,&p->z,t);
  789.                 continue;
  790.             }
  791.             if((to&NQ)==FLOAT||(to&NQ)==DOUBLE){
  792.                 if(isreg(q1)&&fst[0]==p->q1.reg){
  793.                     if((t&NQ)==CHAR){
  794.                         if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,CHAR);
  795.                         fprintf(f,"\tsubl\t$4,%s\n\tfistl\t(%s)\n\tmovsbl\t(%s),%s\n\taddl\t$4,%s\n",regnames[sp],regnames[sp],regnames[sp],regnames[reg],regnames[sp]);
  796.                         move(f,0,reg,&p->z,0,t);
  797.                     }else{
  798.                       if(isreg(z)){
  799.                         fprintf(f,"\tsubl\t$4,%s\n\tfistl\t(%s)\n\tmov%c\t(%s),",regnames[sp],regnames[sp],x_t[t&NQ],regnames[sp]);
  800.                         stackoffset-=4;
  801.                         probj2(f,&p->z,t);fprintf(f,"\n\taddl\t$4,%s\n",regnames[sp]);
  802.                         stackoffset+=4;
  803.                       }else{
  804.                         fprintf(f,"\tfist%c\t",x_t[t&NQ]);
  805.                         probj2(f,&p->z,t);fprintf(f,"\n");
  806.                       }
  807.                     }
  808.                 }else{
  809.                     fload(f,&p->q1,to);
  810.                     if((t&NQ)==CHAR){
  811.                         if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,CHAR);
  812.                         fprintf(f,"\tsubl\t$4,%s\n\tfistpl\t(%s)\n\tmovsbl\t(%s),%s\n\taddl\t$4,%s\n",regnames[sp],regnames[sp],regnames[sp],regnames[reg],regnames[sp]);
  813.                         fpop(); move(f,0,reg,&p->z,0,t);
  814.                     }else{
  815.                       if(isreg(z)){
  816.                         fprintf(f,"\tsubl\t$4,%s\n\tfistpl\t(%s)\n\tmov%c\t(%s),",regnames[sp],regnames[sp],x_t[t&NQ],regnames[sp]);
  817.                         stackoffset-=4;
  818.                         probj2(f,&p->z,t);fprintf(f,"\n\taddl\t$4,%s\n",regnames[sp]);
  819.                         stackoffset+=4;fpop();
  820.                       }else{
  821.                         fprintf(f,"\tfistp%c\t",x_t[t&NQ]);
  822.                         probj2(f,&p->z,t);fprintf(f,"\n");fpop();
  823.                       }
  824.                     }
  825.                 }
  826.                 continue;
  827.             }
  828.             ierror(0);
  829.         }
  830.         if(c==MINUS||c==KOMPLEMENT){
  831.             char *s;
  832.             if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  833.                 if(isreg(z)&&p->z.reg==9&&isreg(q1)&&p->q1.reg==9){
  834.                     fprintf(f,"\tfchs\n");
  835.                     continue;
  836.                 }
  837.                 fload(f,&p->q1,t);
  838.                 fprintf(f,"\tfchs\n");
  839.                 fprintf(f,"\tfstp%c\t",x_t[t&NQ]);
  840.                 probj2(f,&p->z,t);fprintf(f,"\n");
  841.                 fpop();
  842.                 continue;
  843.             }
  844.             if(c==MINUS) s="neg"; else s="not";
  845.             if(compare_objects(&p->q1,&p->q2)){
  846.                 fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
  847.                 probj2(f,&p->z,t);fprintf(f,"\n");
  848.                 continue;
  849.             }
  850.             if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,t);
  851.             move(f,&p->q1,0,0,reg,t);
  852.             fprintf(f,"\t%s%c\t%s\n",s,x_t[t&NQ],regnames[reg]);
  853.             move(f,0,reg,&p->z,0,t);
  854.             continue;
  855.         }
  856.         if(c==SETRETURN){
  857.             if(p->z.reg){
  858.                 if(p->z.reg==9){
  859.                     if(!isreg(q1)||fst[0]!=p->q1.reg)
  860.                         fload(f,&p->q1,t);
  861.                 }else{
  862.                     move(f,&p->q1,0,0,p->z.reg,t);
  863.                 }
  864.             }
  865.             continue;
  866.         }
  867.         if(c==GETRETURN){
  868.             if(p->q1.reg){
  869.                 if(p->q1.reg==9){
  870.                     if(!isreg(z)||fst[0]!=p->z.reg)
  871.                         fstore(f,&p->z,t);
  872.                 }else{
  873.                     move(f,0,p->q1.reg,&p->z,0,t);
  874.                 }
  875.             }
  876.             continue;
  877.         }
  878.         if(c==CALL){
  879.             int reg;
  880.             if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
  881.               fprintf(f,"%s\n",p->q1.v->fi->inline_asm);
  882.             }else{
  883.               if(p->q1.flags&DREFOBJ){
  884.                 if(!(p->q1.flags®)) ierror(0);
  885.                 fprintf(f,"\tcall\t*%s\n",regnames[p->q1.reg]);
  886.               }else{
  887.                 fprintf(f,"\tcall\t");probj2(f,&p->q1,t);
  888.                 fprintf(f,"\n");
  889.               }
  890.             }
  891.             if(!zleqto(l2zl(0L),p->q2.val.vlong)){
  892.               notpopped+=zl2l(p->q2.val.vlong);
  893.               dontpop-=zl2l(p->q2.val.vlong);
  894.               if(!(g_flags[2]&USEDFLAG)&&stackoffset==-notpopped){
  895.                 /*  Entfernen der Parameter verzoegern  */
  896.               }else{
  897.                 fprintf(f,"\taddl\t$%ld,%%esp\n",zl2l(p->q2.val.vlong));
  898.                 stackoffset+=zl2l(p->q2.val.vlong);
  899.                 notpopped-=zl2l(p->q2.val.vlong);
  900.               }
  901.             }
  902.             continue;
  903.         }
  904.         if(c==ASSIGN||c==PUSH){
  905.             if(c==PUSH) dontpop+=zl2l(p->q2.val.vlong);
  906.             if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  907.                 if(c==ASSIGN){
  908.                     prfst(f,"fassign");
  909.                     fload(f,&p->q1,t);
  910.                     fstore(f,&p->z,t);
  911.                     continue;
  912.                 }else if(isreg(q1)){
  913.                     prfst(f,"fpush");
  914.                     fprintf(f,"\tsubl\t$%ld,%s\n",zl2l(sizetab[t&NQ]),regnames[sp]);
  915.                     stackoffset-=zl2l(sizetab[t&NQ]);
  916.                     if(fst[0]==p->q1.reg){
  917.                         fprintf(f,"\tfst%c\t(%s)\n",x_t[t&NQ],regnames[sp]);
  918.                     }else{
  919.                         fload(f,&p->q1,t);
  920.                         fprintf(f,"\tfstp%c\t(%s)\n",x_t[t&NQ],regnames[sp]);
  921.                         fpop();
  922.                     }
  923.                     continue;
  924.                 }
  925.             }
  926.             if((t&NQ)>POINTER||!zleqto(p->q2.val.vlong,sizetab[t&NQ])||!zlleq(p->q2.val.vlong,l2zl(4L))){
  927.                 int mdi=di,msi=si,m=0;long l;
  928.                 l=zl2l(p->q2.val.vlong);
  929.                 if(regs[cx]){m|=1;if(!cxl)cxl=++label;fprintf(f,"\tmovl\t%s,%sl%d\n",regnames[cx],labprefix,cxl);}
  930.                 if(regs[msi]||!regused[msi]){m|=2;if(!sil)sil=++label;fprintf(f,"\tmovl\t%s,%sl%d\n",regnames[msi],labprefix,sil);}
  931.                 if(regs[mdi]||!regused[mdi]){m|=4;if(!dil)dil=++label;fprintf(f,"\tmovl\t%s,%sl%d\n",regnames[mdi],labprefix,dil);}
  932.                 if((p->z.flags®)&&p->z.reg==msi&&(p->q1.flags®)&&p->q1.reg==mdi){
  933.                     msi=di;mdi=si;
  934.                     m|=8;
  935.                 }
  936.                 if(!(p->z.flags®)||p->z.reg!=msi){
  937.                     fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
  938.                     fprintf(f,",%s\n",regnames[msi]);
  939.                 }
  940.                 if(c==PUSH){
  941.                     fprintf(f,"\tsubl\t$%ld,%s\n\tmovl\t%s,%s\n",l,regnames[sp],regnames[sp],regnames[mdi]);
  942.                     stackoffset-=l;
  943.                 }else{
  944.                     fprintf(f,"\tleal\t");probj2(f,&p->z,t);
  945.                     fprintf(f,",%s\n",regnames[mdi]);
  946.                 }
  947.                 if((p->z.flags®)&&p->z.reg==msi){
  948.                     fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
  949.                     fprintf(f,",%s\n",regnames[msi]);
  950.                 }
  951.                 if(m&8){
  952.                     msi=si;mdi=di;
  953.                     fprintf(f,"\txch\t%s,%s\n",regnames[msi],regnames[mdi]);
  954.                 }
  955.                 if((t&NQ)==ARRAY||(t&NQ)==CHAR||l<4){
  956.                     fprintf(f,"\tmovl\t$%ld,%s\n\trep\n\tmovsb\n",l,regnames[cx]);
  957.                 }else{
  958.                     if(l>=8)
  959.                         fprintf(f,"\tmovl\t$%ld,%s\n\trep\n",l/4,regnames[cx]);
  960.                     fprintf(f,"\tmovsl\n");
  961.                     if(l%2) fprintf(f,"\tmovsw\n");
  962.                     if(l%1) fprintf(f,"\tmovsb\n");
  963.                 }
  964.                 if(m&4) fprintf(f,"\tmovl\t%sl%d,%s\n",labprefix,dil,regnames[mdi]);
  965.                 if(m&2) fprintf(f,"\tmovl\t%sl%d,%s\n",labprefix,sil,regnames[msi]);
  966.                 if(m&1) fprintf(f,"\tmovl\t%sl%d,%s\n",labprefix,cxl,regnames[cx]);
  967.                 continue;
  968.             }
  969.             if(t==FLOAT) t=LONG;
  970.             if(c==PUSH){
  971.                 fprintf(f,"\tpush%c\t",x_t[t&NQ]);
  972.                 probj2(f,&p->q1,t);fprintf(f,"\n");
  973.                 stackoffset-=zl2l(p->q2.val.vlong);
  974.                 continue;
  975.             }
  976.             if(c==ASSIGN){
  977.                 if(p->q1.flags&KONST){
  978.                     move(f,&p->q1,0,&p->z,0,t);
  979.                     continue;
  980.                 }
  981.                 if(isreg(z)) reg=p->z.reg;
  982.                 else if(isreg(q1)) reg=p->q1.reg;
  983.                 else reg=get_reg(f,p,t);
  984.                 move(f,&p->q1,0,0,reg,t);
  985.                 move(f,0,reg,&p->z,0,t);
  986.                 continue;
  987.             }
  988.             ierror(0);
  989.         }
  990.         if(c==ADDRESS){
  991.             if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,LONG);
  992.             fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
  993.             fprintf(f,",%s\n",regnames[reg]);
  994.             move(f,0,reg,&p->z,0,POINTER);
  995.             continue;
  996.         }
  997.         if(c==TEST){
  998.             lastcomp=t;
  999.             if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1000.                 if(isreg(q1)&&fst[0]==p->q1.reg){
  1001.                     fprintf(f,"\tftst\n");lastcomp|=UNSIGNED;
  1002.                     continue;
  1003.                 }else{
  1004.                     p->code=c=COMPARE;
  1005.                     p->q2.flags=KONST;
  1006.                     p->q2.val.vdouble=d2zd(0.0);
  1007.                     if((t&NQ)==FLOAT) p->q2.val.vfloat=zd2zf(p->q2.val.vdouble);
  1008.                     /*  fall through to COMPARE */
  1009.                 }
  1010.             }else{
  1011.                 fprintf(f,"\tcmp%c\t$0,",x_t[t&NQ]);
  1012.                 probj2(f,&p->q1,t);fprintf(f,"\n");
  1013.                 continue;
  1014.             }
  1015.         }
  1016.         if(c==COMPARE){
  1017.             lastcomp=t;
  1018.             if(isreg(q2)||(p->q1.flags&KONST)){
  1019.                 struct IC *b=p->next;
  1020.                 struct obj o;
  1021.                 o=p->q1;p->q1=p->q2;p->q2=o;
  1022.                 while(b&&b->code==FREEREG) b=b->next;
  1023.                 if(!b) ierror(0);
  1024.                 if(b->code==BLT) b->code=BGT;
  1025.                 else if(b->code==BLE) b->code=BGE;
  1026.                 else if(b->code==BGT) b->code=BLT;
  1027.                 else if(b->code==BGE) b->code=BLE;
  1028.             }
  1029.             if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1030.                 prfst(f,"fcomp");
  1031.                 if(isreg(q1)&&p->q1.reg==fst[0]){
  1032.                     fprintf(f,"\tfcom%c\t",x_t[t&NQ]);
  1033.                     probj2(f,&p->q2,t);fprintf(f,"\n");
  1034.                 }else{
  1035.                     fload(f,&p->q1,t);
  1036.                     fprintf(f,"\tfcomp%c\t",x_t[t&NQ]);
  1037.                     probj2(f,&p->q2,t);fprintf(f,"\n");
  1038.                     fpop();
  1039.                 }
  1040.                 fprintf(f,"\tfstsw\n\tsahf\n");
  1041.                 lastcomp|=UNSIGNED;
  1042.                 continue;
  1043.             }
  1044.             if(!isreg(q1)){
  1045.                 if(!isreg(q2)){
  1046.                     reg=get_reg(f,p,t);
  1047.                     move(f,&p->q1,0,0,reg,t);
  1048.                     p->q1.flags=REG;
  1049.                     p->q1.reg=reg;
  1050.                 }
  1051.             }
  1052.             fprintf(f,"\tcmp%c\t",x_t[t&NQ]);
  1053.             probj2(f,&p->q2,t);fprintf(f,",");
  1054.             probj2(f,&p->q1,t);fprintf(f,"\n");
  1055.             continue;
  1056.         }
  1057.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1058.             char s[2];
  1059.             prfst(f,"fmath");
  1060.             if(isreg(q2)) s[0]=0; else {s[0]=x_t[t&NQ];s[1]=0;}
  1061.             if(isreg(z)&&isreg(q1)&&p->q1.reg==fst[0]&&p->z.reg==fst[0]){
  1062.                 fprintf(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
  1063.                 probj2(f,&p->q2,t); fprintf(f,"\n");continue;
  1064.             }
  1065.             fload(f,&p->q1,t);
  1066.             fprintf(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
  1067.             probj2(f,&p->q2,t); fprintf(f,"\n");
  1068.             fstore(f,&p->z,t); continue;
  1069.         }
  1070.         if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&(p->q2.flags&KONST)){
  1071.             long ln;
  1072.             eval_const(&p->q2.val,t);
  1073.             if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)){
  1074.                 if(ln=pof2(vulong)){
  1075.                     if(c==MOD){
  1076.                         vlong=zlsub(vlong,l2zl(1L));
  1077.                         p->code=AND;
  1078.                     }else{
  1079.                         vlong=l2zl(ln-1);
  1080.                         if(c==DIV) p->code=RSHIFT; else p->code=LSHIFT;
  1081.                     }
  1082.                     c=p->code;
  1083.                     if((t&NU)==CHAR) p->q2.val.vchar=zl2zc(vlong);
  1084.                     if((t&NU)==SHORT) p->q2.val.vshort=zl2zs(vlong);
  1085.                     if((t&NU)==INT) p->q2.val.vint=zl2zi(vlong);
  1086.                     if((t&NU)==LONG) p->q2.val.vlong=vlong;
  1087.                     vulong=zl2zul(vlong);
  1088.                     if((t&NU)==(UNSIGNED|CHAR)) p->q2.val.vuchar=zul2zuc(vulong);
  1089.                     if((t&NU)==(UNSIGNED|SHORT)) p->q2.val.vushort=zul2zus(vulong);
  1090.                     if((t&NU)==(UNSIGNED|INT))  p->q2.val.vuint=zul2zui(vulong);
  1091.                     if((t&NU)==(UNSIGNED|LONG)) p->q2.val.vulong=vulong;
  1092.                 }
  1093.             }
  1094.         }
  1095.         if(c==MOD||c==DIV){
  1096.             int m=0;
  1097.             if(regs[ax]&&(!isreg(z)||p->z.reg!=ax)){
  1098.                 fprintf(f,"\tpushl\t%s\n",regnames[ax]);
  1099.                 stackoffset-=4;m|=1;
  1100.             }
  1101.             if(regs[dx]&&(!isreg(z)||p->z.reg!=dx)){
  1102.                 fprintf(f,"\tpushl\t%s\n",regnames[dx]);
  1103.                 stackoffset-=4;m|=2;
  1104.             }
  1105.             if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(p->q2.reg==ax||p->q2.reg==dx)){
  1106.                 move(f,&p->q2,0,0,dx,t);
  1107.                 fprintf(f,"\tpushl\t%s\n",regnames[dx]);
  1108.                 m|=8;stackoffset-=4;
  1109.             }
  1110.             move(f,&p->q1,0,0,ax,t);
  1111.             if(p->q2.flags&KONST){
  1112.                 fprintf(f,"\tpush%c\t",x_t[t&NQ]);probj2(f,&p->q2,t);
  1113.                 fprintf(f,"\n");m|=4;stackoffset-=4;
  1114.             }
  1115.             if(t&UNSIGNED) fprintf(f,"\txorl\t%s,%s\n\tdivl\t",regnames[dx],regnames[dx]);
  1116.                 else       fprintf(f,"\tcltd\n\tidivl\t");
  1117.             if((m&12)||(isreg(q2)&&p->q2.reg==dx)){
  1118.                 fprintf(f,"(%s)",regnames[sp]);
  1119.             }else if(isreg(q2)&&p->q2.reg==ax){
  1120.                 fprintf(f,"%s(%s)",(m&2)?"4":"",regnames[sp]);
  1121.             }else{
  1122.                 probj2(f,&p->q2,t);
  1123.             }
  1124.             fprintf(f,"\n");
  1125.             if(c==DIV) move(f,0,ax,&p->z,0,t);
  1126.                 else   move(f,0,dx,&p->z,0,t);
  1127.             if(m&4){ fprintf(f,"\taddl\t$%ld,%s\n",zl2l(sizetab[t&NQ]),regnames[sp]);stackoffset+=4;}
  1128.             if(m&8){ fprintf(f,"\tpopl\t%s\n",regnames[dx]);stackoffset+=4;}
  1129.             if(m&2){ fprintf(f,"\tpopl\t%s\n",regnames[dx]);stackoffset+=4;}
  1130.             if(m&1){ fprintf(f,"\tpopl\t%s\n",regnames[ax]);stackoffset+=4;}
  1131.             continue;
  1132.         }
  1133.         if(!(p->q2.flags&KONST)&&(c==LSHIFT||c==RSHIFT)){
  1134.             char *s=arithmetics[c-LSHIFT];
  1135.             int fl=0;
  1136.             if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
  1137.             if(((p->q1.flags®)&&p->q1.reg==cx)||((p->z.flags®)&&p->z.reg==cx)
  1138.                ||(!compare_objects(&p->q1,&p->z)&&!isreg(q1))){
  1139.                 fl=regs[cx];regs[cx]=2; /* don't want cx */
  1140.                 reg=get_reg(f,p,t);
  1141.                 regs[cx]=fl;
  1142.                 if(isreg(z)&&p->z.reg==cx) fl=0;
  1143.                 if(fl){fprintf(f,"\tpushl\t%s\n",regnames[cx]);stackoffset-=4;}
  1144.                 move(f,&p->q1,0,0,reg,t);
  1145.                 move(f,&p->q2,0,0,cx,t);
  1146.                 fprintf(f,"\t%s%c\t%%cl,%s\n",s,x_t[t&NQ],regnames[reg]);
  1147.                 move(f,0,reg,&p->z,0,t);
  1148.                 if(fl){fprintf(f,"\tpopl\t%s\n",regnames[cx]);stackoffset+=4;}
  1149.                 continue;
  1150.             }else{
  1151.                 if(!isreg(q2)||p->q2.reg!=cx){
  1152.                     if(regs[cx]){fprintf(f,"\tpushl\t%s\n",regnames[cx]);stackoffset-=4;fl=1;}
  1153.                     move(f,&p->q2,0,0,cx,t);
  1154.                 }
  1155.                 if(compare_objects(&p->q1,&p->z)){
  1156.                     fprintf(f,"\t%s%c\t%%cl,",s,x_t[t&NQ]);
  1157.                     probj2(f,&p->z,t);fprintf(f,"\n");
  1158.                 }else{
  1159.                     move(f,0,p->q1.reg,&p->z,0,t);
  1160.                     fprintf(f,"\t%s%c\t%%cl,",s,x_t[t&NQ]);
  1161.                     probj2(f,&p->z,t);fprintf(f,"\n");
  1162.                 }
  1163.                 if(fl) {fprintf(f,"\tpopl\t%s\n",regnames[cx]);stackoffset+=4;}
  1164.                 continue;
  1165.             }
  1166.         }
  1167.         if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)){
  1168.             char *s;
  1169.             if(c>=OR&&c<=AND) s=logicals[c-OR];
  1170.                 else s=arithmetics[c-LSHIFT];
  1171.             if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
  1172.             if(c!=MULT&&compare_objects(&p->q1,&p->z)){
  1173.                 if(isreg(z)||isreg(q1)||(p->q2.flags&KONST)){
  1174.                     if((p->q2.flags&KONST)&&(c==ADD||c==SUB)){
  1175.                         eval_const(&p->q2.val,t);
  1176.                         if(zleqto(vlong,l2zl(1L))&&zuleqto(vulong,ul2zul(1UL))&&zdeqto(vdouble,d2zd(1.0))){
  1177.                             if(c==ADD) s="inc"; else s="dec";
  1178.                             fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
  1179.                             probj2(f,&p->z,t);fprintf(f,"\n");
  1180.                             continue;
  1181.                         }
  1182.                     }
  1183.                     fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
  1184.                     probj2(f,&p->q2,t);fprintf(f,",");
  1185.                     probj2(f,&p->z,t);fprintf(f,"\n");
  1186.                     continue;
  1187.                 }else{
  1188.                     if(isreg(q2)) reg=p->q2.reg; else reg=get_reg(f,p,t);
  1189.                     move(f,&p->q2,0,0,reg,t);
  1190.                     fprintf(f,"\t%s%c\t%s",s,x_t[t&NQ],regnames[reg]);
  1191.                     fprintf(f,","); probj2(f,&p->z,t);fprintf(f,"\n");
  1192.                     continue;
  1193.                 }
  1194.             }
  1195.             if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,t);
  1196.             move(f,&p->q1,0,0,reg,t);
  1197.             if((p->q2.flags&KONST)&&(c==ADD||c==SUB)){
  1198.                 eval_const(&p->q2.val,t);
  1199.                 if(zleqto(vlong,l2zl(1L))&&zuleqto(vulong,ul2zul(1UL))&&zdeqto(vdouble,d2zd(1.0))){
  1200.                     if(c==ADD) s="inc"; else s="dec";
  1201.                     fprintf(f,"\t%s%c\t%s\n",s,x_t[t&NQ],regnames[reg]);
  1202.                 }else{
  1203.                     fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
  1204.                     probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[reg]);
  1205.                 }
  1206.             }else{
  1207.                 fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
  1208.                 probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[reg]);
  1209.             }
  1210.             move(f,0,reg,&p->z,0,t);
  1211.             continue;
  1212.         }
  1213.         ierror(0);
  1214.     }
  1215.     if(notpopped){
  1216.         fprintf(f,"\taddl\t$%ld,%%esp\n",notpopped);
  1217.         stackoffset+=notpopped;notpopped=0;
  1218.     }
  1219.     function_bottom(f,v,loff);
  1220. }
  1221.  
  1222. int shortcut(int code,int typ)
  1223. {
  1224.     return(0);
  1225. }
  1226.  
  1227. void cleanup_cg(FILE *f)
  1228. {
  1229.     struct fpconstlist *p;
  1230.     unsigned char *ip;
  1231.     while(p=firstfpc){
  1232.         if(f){
  1233.             if(section!=CODE){fprintf(f,codename);section=CODE;}
  1234.             fprintf(f,"\t.align\t4\n");
  1235.             fprintf(f,"%sl%d:\n\t.long\t",labprefix,p->label);
  1236.             ip=(unsigned char *)&p->val.vdouble;
  1237.             fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  1238.             if((p->typ&NQ)==DOUBLE){
  1239.                 fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  1240.             }
  1241.             fprintf(f,"\n");
  1242.         }
  1243.         firstfpc=p->next;
  1244.         free(p);
  1245.     }
  1246.     if(f){
  1247.         if(section!=BSS){fprintf(f,bssname);section=BSS;}
  1248.         if(cxl) fprintf(f,"\t.lcomm\t%sl%d,4\n",labprefix,cxl);
  1249.         if(sil) fprintf(f,"\t.lcomm\t%sl%d,4\n",labprefix,sil);
  1250.         if(dil) fprintf(f,"\t.lcomm\t%sl%d,4\n",labprefix,dil);
  1251.     }
  1252. }
  1253.  
  1254.